#   This program is free software; you can redistribute it and/or modify
#   it under the terms of the version 3 of the GNU Lesser General Public License
#   as published by the Free Software Foundation.
#
#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.
#
#   You should have received a copy of the GNU Lesser General Public License
#   along with this program; if not, write to the Free Software
#   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
# Copyright (c) NEC Deutschland GmbH, NEC HPC Europe
import os
import sys
import logging

from aggmon.channel import ChannelComponent
from mon_hierarchy import HierarchyComponent
from aggmon.parse_configs import parse_aggregator_config, parse_importer_config, parse_database_config
from aggmon.aggmon_component import Components
from basic_types.helpers import md5sum_file


__all__ = ['options', 'components', "check_simple_hierarchy", "load_simple_config", "start_simple_config"]


options = None
components = None


def config_hierarchy( components ):
    global options
    # initialize hierarchy component
    if options.hierarchy_cfg is not None:
        # use hierarchy specified in file
        h_file = options.hierarchy_cfg
        try:
            f = open( h_file, "r" )
        except:
            logging.error( "Failed to open hierarchy file %s" % h_file )
            return
        file_sum = md5sum_file( f )
        f.close()

        kwds = { "config_file": h_file, "md5sum": file_sum, "verbose": True }

    else:
        # trivial hierarchy (own host is universe master)
        h_string = "/%s m:/" % (options.hostname)
        kwds = { "config_string": h_string, "verbose": True }

    components.add( HierarchyComponent( kwds=kwds ) )


def check_simple_hierarchy():
    hierarchy = Components.alive["Hierarchy"].instance
    if hierarchy is None:
        logging.error( "No hierarchy information available!" )
        sys.exit( 1 )
    if hierarchy.get_own_host() is None:
        logging.error( "Could not identify own host in hierarchy!" )
        sys.exit( 2 )
    if len( hierarchy.get_group_names() ) > 1:
        logging.error( "This program is only for limited, flat hierarchies! Exiting." )
        sys.exit( 3 )
    hierarchy.print_info()


def load_simple_config():
    # TODO: this function is special and only good for the trivial hierarchy! Write another one for arbitrary hierarchies!
    global options

    components = Components()

    config_hierarchy( components )
    if os.path.exists( options.aggregator_conf_file ):
        parse_aggregator_config( components, file_name=options.aggregator_conf_file, group_path="/" )
    if os.path.exists( options.importer_conf_file ):
        parse_importer_config( components, file_name=options.importer_conf_file )
    if os.path.exists( options.database_conf_file ):
        parse_database_config( components, file_name=options.database_conf_file )

    components.add( ChannelComponent( options.metric_channel, name="GroupChannel", requires_re=["Hierarchy"] ) )
    components.update_all_deps_reqs()
    return components


def start_simple_config( passed_components ):
    # TODO: for a complex hierarchy the channels must be configured more smartly
    global options, components

    components = passed_components
    components.make_alive()
    Components.alive.start_all( hostpath = options.hostname,
                                hierarchy = (lambda: Components.alive['Hierarchy'].instance),  # deferred evaluation
                                input_channel = (lambda: Components.alive['GroupChannel'].instance),
                                group_channels = (lambda: [Components.alive['GroupChannel'].instance]),
                                upstream_channels = (lambda: [Components.alive['GroupChannel'].instance]) )
